home *** CD-ROM | disk | FTP | other *** search
- #ifndef lint
- static char rcsid[] =
- "@(#) $Header: phase.c,v 1.2 88/08/26 22:29:42 jef Exp $ (LBL)";
- #endif
-
- /* phase.c - routines to calculate the phase of the moon
- **
- ** Adapted from "moontool.c" by John Walker, Release 2.0.
- */
-
- /*
- * Extra stuff for `phoon' purpose removed Thu Feb 24 10:34:34 1994 too
- */
-
- #include <math.h>
- #include "tws.h"
-
- /* Astronomical constants. */
-
- #define epoch 2444238.5 /* 1980 January 0.0 */
-
- /* Constants defining the Sun's apparent orbit. */
-
- #define elonge 278.833540 /* ecliptic longitude of the Sun
- at epoch 1980.0 */
- #define elongp 282.596403 /* ecliptic longitude of the Sun at
- perigee */
- #define eccent 0.016718 /* eccentricity of Earth's orbit */
- #define sunsmax 1.495985e8 /* semi-major axis of Earth's orbit, km */
- #define sunangsiz 0.533128 /* sun's angular size, degrees, at
- semi-major axis distance */
-
- /* Elements of the Moon's orbit, epoch 1980.0. */
-
- #define mmlong 64.975464 /* moon's mean lonigitude at the epoch */
- #define mmlongp 349.383063 /* mean longitude of the perigee at the
- epoch */
- #define mlnode 151.950429 /* mean longitude of the node at the
- epoch */
- #define minc 5.145396 /* inclination of the Moon's orbit */
- #define mecc 0.054900 /* eccentricity of the Moon's orbit */
- #define mangsiz 0.5181 /* moon's angular size at distance a
- from Earth */
- #define msmax 384401.0 /* semi-major axis of Moon's orbit in km */
- #define mparallax 0.9507 /* parallax at distance a from Earth */
- #define synmonth 29.53058868 /* synodic month (new Moon to new Moon) */
- #define lunatbase 2423436.0 /* base date for E. W. Brown's numbered
- series of lunations (1923 January 16) */
-
- /* Properties of the Earth. */
-
- #define earthrad 6378.16 /* radius of Earth in kilometres */
-
-
- #define PI 3.14159265358979323846 /* assume not near black hole nor in
- Tennessee */
-
- /* Handy mathematical functions. */
-
- #define sgn(x) (((x) < 0) ? -1 : ((x) > 0 ? 1 : 0)) /* extract sign */
- #define abs(x) ((x) < 0 ? (-(x)) : (x)) /* absolute val */
- #define fixangle(a) ((a) - 360.0 * (floor((a) / 360.0))) /* fix angle */
- #define torad(d) ((d) * (PI / 180.0)) /* deg->rad */
- #define todeg(d) ((d) * (180.0 / PI)) /* rad->deg */
- #define dsin(x) (sin(torad((x)))) /* sin from deg */
- #define dcos(x) (cos(torad((x)))) /* cos from deg */
-
-
- /* jdate - convert internal GMT date and time to Julian day and fraction */
-
- static long jdate(t)
- struct tws *t;
- {
- long c, m, y;
-
- y = t->tw_year + 1900;
- m = t->tw_mon + 1;
- if (m > 2)
- m = m - 3;
- else {
- m = m + 9;
- y--;
- }
- c = y / 100L; /* compute century */
- y -= 100L * c;
- return t->tw_mday + (c * 146097L) / 4 + (y * 1461L) / 4 +
- (m * 153L + 2) / 5 + 1721119L;
- }
-
- /* jtime - convert internal date and time to astronomical Julian
- ** time (i.e. Julian date plus day fraction, expressed as
- ** a double)
- */
-
- double jtime(struct tws * t)
- {
- int c;
-
- c = - t->tw_zone;
- if ( t->tw_flags & TW_DST )
- /* c += 60; */
- c -= 60; /* at least in Finland daylight time is one hour more */
-
- return (jdate(t) - 0.5) +
- (t->tw_sec + 60 * (t->tw_min + c + 60 * t->tw_hour)) / 86400.0;
- }
-
- /* kepler - solve the equation of Kepler */
-
- static double kepler(double m, double ecc)
- {
- double e, delta;
- #define EPSILON 1E-6
-
- e = m = torad(m);
- do {
- delta = e - ecc * sin(e) - m;
- e -= delta / (1 - ecc * cos(e));
- } while (abs(delta) > EPSILON);
- return e;
- }
-
- /* phase - calculate phase of moon as a fraction:
- **
- ** The argument is the time for which the phase is requested,
- ** expressed as a Julian date and fraction. Returns the terminator
- ** phase angle as a percentage of a full circle (i.e., 0 to 1),
- ** and stores into pointer arguments the illuminated fraction of
- ** the Moon's disc, the Moon's age in days and fraction, the
- ** distance of the Moon from the centre of the Earth, and the
- ** angular diameter subtended by the Moon as seen by an observer
- ** at the centre of the Earth.
- */
-
- double phase(pdate, pphase, mage, dist, angdia, sudist, suangdia)
- double pdate;
- double *pphase; /* illuminated fraction */
- double *mage; /* age of moon in days */
- double *dist; /* distance in kilometres */
- double *angdia; /* angular diameter in degrees */
- double *sudist; /* distance to Sun */
- double *suangdia; /* sun's angular diameter */
- {
- double Day, N, M, Ec, Lambdasun, ml, MM, MN, Ev, Ae, A3, MmP,
- mEc, A4, lP, V, lPP, NP, y, x, Lambdamoon, BetaM,
- MoonAge, MoonPhase,
- MoonDist, MoonDFrac, MoonAng, MoonPar,
- F, SunDist, SunAng;
-
- /* Calculation of the Sun's position. */
-
- Day = pdate - epoch; /* date within epoch */
- N = fixangle((360 / 365.2422) * Day); /* mean anomaly of the Sun */
- M = fixangle(N + elonge - elongp); /* convert from perigee
- co-ordinates to epoch 1980.0 */
- Ec = kepler(M, eccent); /* solve equation of Kepler */
- Ec = sqrt((1 + eccent) / (1 - eccent)) * tan(Ec / 2);
- Ec = 2 * todeg(atan(Ec)); /* true anomaly */
- Lambdasun = fixangle(Ec + elongp); /* Sun's geocentric ecliptic
- longitude */
- /* Orbital distance factor. */
- F = ((1 + eccent * cos(torad(Ec))) / (1 - eccent * eccent));
- SunDist = sunsmax / F; /* distance to Sun in km */
- SunAng = F * sunangsiz; /* Sun's angular size in degrees */
-
- /* Calculation of the Moon's position. */
-
- /* Moon's mean longitude. */
- ml = fixangle(13.1763966 * Day + mmlong);
-
- /* Moon's mean anomaly. */
- MM = fixangle(ml - 0.1114041 * Day - mmlongp);
-
- /* Moon's ascending node mean longitude. */
- MN = fixangle(mlnode - 0.0529539 * Day);
-
- /* Evection. */
- Ev = 1.2739 * sin(torad(2 * (ml - Lambdasun) - MM));
-
- /* Annual equation. */
- Ae = 0.1858 * sin(torad(M));
-
- /* Correction term. */
- A3 = 0.37 * sin(torad(M));
-
- /* Corrected anomaly. */
- MmP = MM + Ev - Ae - A3;
-
- /* Correction for the equation of the centre. */
- mEc = 6.2886 * sin(torad(MmP));
-
- /* Another correction term. */
- A4 = 0.214 * sin(torad(2 * MmP));
-
- /* Corrected longitude. */
- lP = ml + Ev + mEc - Ae + A4;
-
- /* Variation. */
- V = 0.6583 * sin(torad(2 * (lP - Lambdasun)));
-
- /* True longitude. */
- lPP = lP + V;
-
- /* Corrected longitude of the node. */
- NP = MN - 0.16 * sin(torad(M));
-
- /* Y inclination coordinate. */
- y = sin(torad(lPP - NP)) * cos(torad(minc));
-
- /* X inclination coordinate. */
- x = cos(torad(lPP - NP));
-
- /* Ecliptic longitude. */
- Lambdamoon = todeg(atan2(y, x));
- Lambdamoon += NP;
-
- /* Ecliptic latitude. */
- BetaM = todeg(asin(sin(torad(lPP - NP)) * sin(torad(minc))));
-
- /* Calculation of the phase of the Moon. */
-
- /* Age of the Moon in degrees. */
- MoonAge = lPP - Lambdasun;
-
- /* Phase of the Moon. */
- MoonPhase = (1 - cos(torad(MoonAge))) / 2;
-
- /* Calculate distance of moon from the centre of the Earth. */
-
- MoonDist = (msmax * (1 - mecc * mecc)) /
- (1 + mecc * cos(torad(MmP + mEc)));
-
- /* Calculate Moon's angular diameter. */
-
- MoonDFrac = MoonDist / msmax;
- MoonAng = mangsiz / MoonDFrac;
-
- /* Calculate Moon's parallax. */
-
- MoonPar = mparallax / MoonDFrac;
-
- *pphase = MoonPhase;
- *mage = synmonth * (fixangle(MoonAge) / 360.0);
- *dist = MoonDist;
- *angdia = MoonAng;
- *sudist = SunDist;
- *suangdia = SunAng;
- return torad(fixangle(MoonAge));
- }
-